package free.order.security;

import java.util.Collections;
import java.util.Iterator;
import java.util.List;

import org.acegisecurity.ConfigAttributeDefinition;
import org.acegisecurity.ConfigAttributeEditor;
import org.acegisecurity.GrantedAuthority;
import org.acegisecurity.intercept.web.AbstractFilterInvocationDefinitionSource;
import org.apache.oro.text.regex.MalformedPatternException;
import org.apache.oro.text.regex.Pattern;
import org.apache.oro.text.regex.PatternMatcher;
import org.apache.oro.text.regex.Perl5Compiler;
import org.apache.oro.text.regex.Perl5Matcher;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.PathMatcher;
import free.order.security.cache.AcegiCacheManager;
import  free.order.security.resource.ResourceDetails;

/**
 * @author cac
 */
public class DBFilterInvocationDefinitionSource extends
		AbstractFilterInvocationDefinitionSource {

	private boolean convertUrlToLowercaseBeforeComparison = false;

	private boolean useAntPath = false;

	private final PathMatcher pathMatcher = new AntPathMatcher();

	private final PatternMatcher matcher = new Perl5Matcher();


	private AcegiCacheManager acegiCacheManager;

	public void setAcegiCacheManager(AcegiCacheManager acegiCacheManager) {
		this.acegiCacheManager = acegiCacheManager;
	}

	/**
	 * 返回当�?URL对应的ROLE
	 *
	 * @see org.acegisecurity.intercept.web.AbstractFilterInvocationDefinitionSource#lookupAttributes(java.lang.String)
	 */
	@Override
	@SuppressWarnings("unchecked")
	public ConfigAttributeDefinition lookupAttributes(String url) {
		acegiCacheManager.initResourceCache();

		if (isUseAntPath()) {
			// Strip anything after a question mark symbol, as per SEC-161.
			int firstQuestionMarkIndex = url.lastIndexOf("?");

			if (firstQuestionMarkIndex != -1) {
				url = url.substring(0, firstQuestionMarkIndex);
			}
		}

		List urls = acegiCacheManager.getUrlResStrings();

		//倒�?�排�?
		Collections.sort(urls);
		Collections.reverse(urls);

		if (convertUrlToLowercaseBeforeComparison) {
			url = url.toLowerCase();
		}

		GrantedAuthority[] authorities = new GrantedAuthority[0];
		for (Iterator iterator = urls.iterator(); iterator.hasNext();) {
			String resString = (String) iterator.next();
			boolean matched = false;
			if (isUseAntPath()) {
				matched = pathMatcher.match(resString, url);
			} else {
				Pattern compiledPattern;
				Perl5Compiler compiler = new Perl5Compiler();
				try {
					compiledPattern = compiler.compile(resString, Perl5Compiler.READ_ONLY_MASK);
				} catch (MalformedPatternException mpe) {
					throw new IllegalArgumentException("Malformed regular expression: " + resString, mpe);
				}

				matched = matcher.matches(url, compiledPattern);
			}
			if (matched) {
				ResourceDetails rd = acegiCacheManager.getAuthorityFromCache(resString);
				authorities = rd.getAuthorities();
				break;
			}
		}

		if (authorities.length > 0) {
			String authoritiesStr = " ";
			for (int i = 0; i < authorities.length; i++) {
				authoritiesStr += authorities[i].getAuthority() + ",";
			}
			String authStr = authoritiesStr.substring(0, authoritiesStr
					.length() - 1);
			ConfigAttributeEditor configAttrEditor = new ConfigAttributeEditor();
			configAttrEditor.setAsText(authStr.trim());
			return (ConfigAttributeDefinition) configAttrEditor.getValue();
		}


		return null;
	}

	public Iterator getConfigAttributeDefinitions() {
		return null;
	}

	public void setConvertUrlToLowercaseBeforeComparison(
			boolean convertUrlToLowercaseBeforeComparison) {
		this.convertUrlToLowercaseBeforeComparison = convertUrlToLowercaseBeforeComparison;
	}

	public boolean isConvertUrlToLowercaseBeforeComparison() {
		return convertUrlToLowercaseBeforeComparison;
	}

	public boolean isUseAntPath() {
		return useAntPath;
	}

	public void setUseAntPath(boolean useAntPath) {
		this.useAntPath = useAntPath;
	}

}
